#include "fps-thread.hh"

#include "server.hh"

FpsThread::FpsThread (Server* s,
		      const tbb::concurrent_hash_map<int, boost::shared_ptr<Client> >& cl,
		      ObjVect* objvect,
		      tbb::concurrent_hash_map<int, boost::shared_ptr<Client> >::accessor& acc):
  GameThread (s, cl, objvect),
  players_ (),
  oct_ (new OctreeFps (128, 128))
{
  Map* m = new Map (128, 128);

  oct_->map_set (m);

  players_.insert (std::make_pair (acc->first, acc->second));
  Player* p = new Player ();
  gm_.add_player (p);
  t_ = boost::thread (&FpsThread::run, this);
}

FpsThread::~FpsThread ()
{
}

void
FpsThread::add_player (int id, boost::shared_ptr<Client> player)
{
  players_.insert (std::make_pair (id, player));
  Player* p = new Player ();
  gm_.add_player (p);

  player->send_map (oct_);
}

void
FpsThread::add_obj (Object* obj)
{
  objvect_->add (obj);
  std::cout << "add obj" << std::endl;
  oct_->add_obj (obj);

  //sending it to the clients
  tbb::concurrent_hash_map<int, boost::shared_ptr<Client> >::const_iterator it;
  for (it = players_.begin (); it != players_.end (); ++it)
  {
    if (!it->second->locked ())
      it->second->nm ()->send (RType::GET_OBJECT, obj->tonet ());
  }
}

void
FpsThread::remove_player (int id)
{
  players_.erase (id);
}

void
FpsThread::run ()
{
  Physic phy = Physic (*objvect_);

  // uncomment if you want to disconnect the server after all clients are gone

  // bool toto = false;
  double current = SDL_GetTicks ();
  double elapsed = 0;
  double start = SDL_GetTicks ();

  std::cout << "players size = " << players_.size () << std::endl;
  while (!players_.empty ())
  {
    if (gm_.is_winner ())
    {
      std::cout << "The winner is: " << gm_.winner () << std::endl;
      break;
    }
    // std::cout << "SIZE = " << players_.size () << std::endl;
    boost::shared_ptr<Request> req;

    if (r_.try_pop (req))
      (*req) (&rh_);

    if (SDL_GetTicks () - start > 100)
      start = SDL_GetTicks ();

    elapsed = SDL_GetTicks () - current;
    current = SDL_GetTicks ();
    // if (nbclients_)
    //   toto = true;

    // if (toto && !nbclients_)
    //   break;
    if (elapsed >= Physic::TIMESTEP)
    {
//       phy.update (Physic::TIMESTEP);
//       if (!phy.mov_obj ().empty ())
// 	send_physic_updates (phy.mov_obj ());
      elapsed -= Physic::TIMESTEP;
    }
  }

  std::cout << "deleting FPS mode" << std::endl;

  delete oct_;
}
